package ext;

import image.Image3;
import image.ImageGroup;
import image.disk.FormatPNG;
import image.ps.PixelShader;
import image.synth.Synthesizer;
import math.vec2;
import math.vec2i;
import math.vec3;

public class ProgGen
{
    
    public static void main(String[] args)
    {
        Synthesizer synth = new Synthesizer();
        
        vec2i mstart = new vec2i(0, 0);
        vec2i msize = new vec2i(1024);
        
        ImageGroup target = new ImageGroup(1);
        target.attach(0, new Image3(msize));
        synth.rTarget = target;
        
        PSGen psm = new PSGen();
        psm.mTargetI3 = 0;
        synth.computeImage(psm, mstart, msize);
        
        Image3.clampAll(target.image3(0), 0.0, 1.0);
        FormatPNG.save(target.image3(0), "GENERATED");
    }
    
    public static class PSGen extends PixelShader
    {
        
        public int mTargetI3;
        
        
        public PSGen()
        {
            super();
        }
        
        
        public PixelShader copy()
        {
            PSGen copy = new PSGen();
            return copy;
        }
        
        
        public void shade(
                ImageGroup aTarget, 
                vec2i aImagePixel, 
                vec2i aImageSize)
        {
            vec2 unitPixPos = vec2.div(new vec2(aImagePixel), new vec2(aImageSize));
            double r = this.rand(unitPixPos);
            vec3 datum = new vec3(r);
            aTarget.image3(this.mTargetI3).write(aImagePixel, datum);
        }
        
        
        private double rand(vec2 seed)
        {
            double sx = seed.x;
            double sy = seed.y;
            double seedx = this.mod(1.1 * sx + 0.5 * sy, 1.0);
            double seedy = this.mod(0.6 * sx + 1.0 * sy, 1.0);
            double r = 0.5 * (seedx + seedy);
            double s = 0.5 * (1.0 - seedx + seedy);
            
            final double mr = 1.0e-3;
            final double ms = 1.0e-3;
            final double rmr = 1.0 / mr;
            final double rms = 1.0 / ms;
            
            double rm = this.mod(r, mr) * rmr;
            double rs = 1.0 - this.mod(s, ms) * rms;
            
            double result = 0.5 * (rm + rs);
            return result;
        }
        
        private double mod(double a, double b)
        {
            return a - b * (int)(a / b);
        }
        
    }
    
}
